#include "RtspDecodeSoft.h"

RtspDecodeSoft::RtspDecodeSoft(QObject *parent)
    : QObject(parent)
{
    avformat_network_init();
}

RtspDecodeSoft::~RtspDecodeSoft()
{
}

//打开rtsp流
bool RtspDecodeSoft::open(const std::string& url){
    AVDictionary* options = nullptr;
    av_dict_set(&options, "rtsp_transport", "tcp", 0); // 使用TCP传输

    // 打开输入流并查找流信息
    int ret = avformat_open_input(&formatContext, url.c_str(), nullptr, nullptr);
    if (ret < 0) {
        qDebug() << "Could not open source file:" << url.c_str();
        return false;
    }

    // 查找流信息
    ret = avformat_find_stream_info(formatContext, nullptr);
    if (ret < 0) {
        qDebug() << "Could not find stream information";
        return false;
    }

    // 打印流信息
    std::cout << "打印相关信息\n";
    av_dump_format(formatContext, 0, url.c_str(), 0);

    // 查找视频流
    videoStream = nullptr;
    for (unsigned int i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream = formatContext->streams[i];
            break;
        }
    }
    if (!videoStream) {
        qDebug() << "Could not find video stream";
        return false;
    }

    // 查找并打开解码器
    AVCodec *codec = avcodec_find_decoder(videoStream->codecpar->codec_id);
    if (!codec) {
        qDebug() << "Codec not found";
        return false;
    }
    //编解码
    codecContext = avcodec_alloc_context3(codec);
    if (!codecContext) {
        qDebug() << "Could not allocate video codec context";
        return false;
    }
    //将视频流的编解码器参数复制到刚分配的编解码器上下文中
    ret = avcodec_parameters_to_context(codecContext, videoStream->codecpar);
    if (ret < 0) {
        qDebug() << "Could not copy codec parameters to codec context";
        return false;
    }
    //打开编解码器
    ret = avcodec_open2(codecContext, codec, nullptr);
    if (ret < 0) {
        qDebug() << "Could not open codec";
        return false;
    }

    // 初始化图像转换上下文
    swsContext = sws_getContext(
        codecContext->width,    //原始帧图像宽度
        codecContext->height,   //原始帧图像高度
        codecContext->pix_fmt,  //原始帧图像格式
        1280,        //处理后的图像宽度
        720,       //处理后的图像高度
        AV_PIX_FMT_RGB24,       //处理后的图像格式
        SWS_BILINEAR,
        nullptr,
        nullptr,
        nullptr
    );
    if (!swsContext) {
        // 处理错误：无法创建SwsContext
        qDebug() << "Could not allocate swsContext";
        return false;
    }else{
        
    }
    return true;
}

void RtspDecodeSoft::close() {
    if (formatContext) {
        avformat_close_input(&formatContext);
    }
    if (codecContext) {
        avcodec_free_context(&codecContext);
    }
    if (swsContext) {
        sws_freeContext(swsContext);
    }
}
//解包，返回包
bool RtspDecodeSoft::decode_one_packet(AVPacket *packet){
    while ((av_read_frame(formatContext, packet) >= 0)){
        if (packet->stream_index == videoStream->index) 
        {
            int ret = avcodec_send_packet(codecContext, packet);
            if (ret < 0) {
                qDebug() << "Error sending a packet for decoding";
                return false;
            }
            break;
        }
    }
    return true;
}

//解码一帧
// bool RtspDecodeSoft::decode_one_frame(AVPacket *packet,uint8_t *rgbFrame_dst,int *dstStride){

//     AVFrame* frame = av_frame_alloc();
//     if (!frame) {
//         qDebug() << "Could not allocate frame";
//         return false;
//     }

//     while (ret >= 0) 
//     {
//         ret = avcodec_receive_frame(codecContext, frame);//获得解码数据
//         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
//             //结束了
//         } else if (ret < 0) {
//             qDebug() << "Error during decoding";
//             return false;
//         }
//         // 确保frame->data不为NULL
//         if (!frame->data) {
//             qDebug() << "Frame data is NULL";
//             return false;
//         }

//         auto zero = std::chrono::high_resolution_clock::now();
//         // 进行格式转换和分辨率转换
//         sws_scale(
//             swsContext,//转换的上下文
//             (const uint8_t * const *)frame->data,//输入图像数据的指针数组
//             frame->linesize,//输入图像每一行或每一列的步长数组
//             0,//// 输入图像的起始 y 坐标
//             frame->height,//输入图像的高
//             rgbFrame_dst,//指向输出图像数据的指针数组
//             dstStride//输出图像每一行或每一列的步长数组
//         );
//         break;
//     }

//     av_frame_free(&frame);
// }

//解码一帧
bool RtspDecodeSoft::decode_one_frame_toQImage(AVPacket *packet,QImage& img){
    int ret=0;

    AVFrame* frame = av_frame_alloc();
    if (!frame) {
        qDebug() << "Could not allocate frame";
        return false;
    }

    // 转换图像格式并发出信号(使用QImage来接收sws_scale函数的输出)
    img = QImage(1280, 720, QImage::Format_RGB888);
    uint8_t* rgbFrame_dst[] = { img.bits() };//地址指定
    int dstStride[4];
    av_image_fill_linesizes(dstStride, AV_PIX_FMT_RGB24, 1280);


    ret = avcodec_receive_frame(codecContext, frame);
    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
        //结束了
    } else if (ret < 0) {
        qDebug() << "Error during decoding";
        return false;
    }
    // 确保frame->data不为NULL
    if (!frame->data) {
        qDebug() << "Frame data is NULL";
        return false;
    }

    // 进行格式转换和分辨率转换
    sws_scale(
        swsContext,//转换的上下文
        (const uint8_t * const *)frame->data,//输入图像数据的指针数组
        frame->linesize,//输入图像每一行或每一列的步长数组
        0,//// 输入图像的起始 y 坐标
        frame->height,//输入图像的高
        rgbFrame_dst,//指向输出图像数据的指针数组
        dstStride//输出图像每一行或每一列的步长数组
    );


    av_frame_free(&frame);
    return true;
}
